package com.zxy.express.service.impl;

import com.autopai.base.common.mybatis.service.impl.BaseServiceImpl;
import com.autopai.base.common.tools.utils.JsonUtil;
import com.autopai.base.common.web.constant.Constant;
import com.autopai.base.common.web.convert.ConvertUtils;
import com.autopai.base.common.web.model.RestResult;
import com.autopai.base.common.web.page.PageData;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.zxy.express.common.MyConstant;
import com.zxy.express.config.ExpressCoreConfig;
import com.zxy.express.dao.UserDao;
import com.zxy.express.dto.*;
import com.zxy.express.entity.UserEntity;
import com.zxy.express.exception.ModuleErrorCode;
import com.zxy.express.service.UserService;
import com.zxy.express.util.AESUtils;
import com.zxy.express.util.JwtUtils;
import com.zxy.express.util.Sha1;
import com.zxy.express.util.wechat.MiniProgramUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.util.*;

/**
 * 用户信息表
 *
 * @author zhangxiying ${email}
 * @since ${version} 2025-07-01
 */
@Service
@Slf4j
public class UserServiceImpl extends BaseServiceImpl<UserDao, UserEntity> implements UserService {
    @Autowired
    private JwtUtils jwtUtils;
    @Autowired
    private ExpressCoreConfig expressCoreConfig;

    @Override
    public PageData<UserDTO> page(Map<String, Object> params) {
        IPage<UserEntity> page = baseDao.selectPage(
                getPage(params, Constant.CREATE_DATE, false),
                getWrapper(params)
        );

        return getPageData(page, UserDTO.class);
    }

    @Override
    public List<UserDTO> list(Map<String, Object> params) {
        List<UserEntity> entityList = baseDao.selectList(getWrapper(params));

        return ConvertUtils.sourceToTarget(entityList, UserDTO.class);
    }

    private QueryWrapper<UserEntity> getWrapper(Map<String, Object> params){
        String id = (String)params.get("id");
        String openId=(String)params.get("openId");

        QueryWrapper<UserEntity> wrapper = new QueryWrapper<>();
        wrapper.eq(StringUtils.isNotBlank(id), "id", id);
        wrapper.eq(StringUtils.isNotEmpty(openId), "open_id", openId);
        return wrapper;
    }

    @Override
    public UserDTO get(String id) {
        UserEntity entity = baseDao.selectById(id);

        return ConvertUtils.sourceToTarget(entity, UserDTO.class);
    }

    @Override
    public void save(UserDTO dto) {
        UserEntity entity = ConvertUtils.sourceToTarget(dto, UserEntity.class);

        insert(entity);
    }

    @Override
    public void update(UserDTO dto) {
        UserEntity entity = ConvertUtils.sourceToTarget(dto, UserEntity.class);

        updateById(entity);
    }

    @Override
    public void delete(String[] ids) {
        //逻辑删除
        //logicDelete(ids, UserEntity.class);

        //物理删除
        baseDao.deleteBatchIds(Arrays.asList(ids));
    }

    @Override
    public RestResult login(WxUserRegisterRequest request) throws Exception {
        WxUserLoginResponse userLoginResponse = new WxUserLoginResponse();
        //1、根据wxcode获取openid
        SessionInfo sessionInfo = getSessionByWxCode(request.getWxCode(), request.getAppId());
        if (sessionInfo == null || sessionInfo.getOpenid() == null || ("").equals(sessionInfo.getOpenid())) {
            return new RestResult().error(ModuleErrorCode.LOGIN_FAILED);
        }
        String openId = sessionInfo.getOpenid();
        log.info("微信小程序登陆：获取openid , wxcode:{},openid：{}", request.getWxCode(), openId);
        userLoginResponse.setOpenId(openId);
        if (StringUtils.isNotEmpty(sessionInfo.getUnionid())) {
            userLoginResponse.setUnionId(sessionInfo.getUnionid());
        }

        //3、根据openid获取用户信息
        Map<String,Object> map=new HashMap<>(2);
        map.put("openId", openId);
        List<UserDTO> users = list(map);
        //注册
        if(CollectionUtils.isEmpty(users)){
           return new RestResult().error(ModuleErrorCode.USER_NOT_EXIST);
        }
        UserDTO userDTO = users.get(0);
        //登录
        //token生成
        userLoginResponse.setNickName(userDTO.getNickName());
        userLoginResponse.setToken(jwtUtils.generateToken(userDTO.getId()));
        userLoginResponse.setDataKey(AESUtils.aesEncrypts(sessionInfo.getSession_key(), MyConstant.SESSION_KEYSEED));
        return new RestResult().ok(userLoginResponse);
    }

    @Override
    public RestResult register(WxUserRegisterRequest request) throws Exception {
        WxUserLoginResponse userLoginResponse = new WxUserLoginResponse();
        //1、根据wxcode获取openid
        SessionInfo sessionInfo = getSessionByWxCode(request.getWxCode(), request.getAppId());
        if (sessionInfo == null || sessionInfo.getOpenid() == null || ("").equals(sessionInfo.getOpenid())) {
            return new RestResult().error(ModuleErrorCode.LOGIN_FAILED);
        }
        String openId = sessionInfo.getOpenid();
        log.info("微信小程序登陆：获取openid , wxcode:{},openid：{}", request.getWxCode(), openId);
        userLoginResponse.setOpenId(openId);
        if (StringUtils.isNotEmpty(sessionInfo.getUnionid())) {
            userLoginResponse.setUnionId(sessionInfo.getUnionid());
        }

        //3、根据openid获取用户信息
        Map<String,Object> map=new HashMap<>(2);
        map.put("openId", openId);
        List<UserDTO> users = list(map);
        UserDTO userDTO;
        //注册
        if(CollectionUtils.isEmpty(users)){
            //验证签名
//            String sign = Sha1.getSha1(request.getRawData() + sessionInfo.getSession_key());
//            log.info("签名:{},参数:{}", sign, JsonUtil.obj2String(request.getRawData()));
//            if (!sign.equals(request.getSignature())) {
//                log.error("原始签名：{},新签名:{}", request.getSignature(), sign);
//                return new RestResult().error(ModuleErrorCode.FAILED_WX_SIGN_ERROR);
//            }
            UserEntity entity = insertWxUser(request, sessionInfo);
            if(entity.getId()==null){
                log.error("注册用户失败：{}",openId);
                return new RestResult().error(ModuleErrorCode.LOGIN_FAILED);
            }
            userDTO = ConvertUtils.sourceToTarget(entity, UserDTO.class);

        }else {
            userDTO = users.get(0);
        }
        //登录
        //token生成
        userLoginResponse.setNickName(userDTO.getNickName());
        userLoginResponse.setToken(jwtUtils.generateToken(userDTO.getId()));
        userLoginResponse.setDataKey(AESUtils.aesEncrypts(sessionInfo.getSession_key(), MyConstant.SESSION_KEYSEED));
        return new RestResult().ok(userLoginResponse);
    }

    @Override
    public RestResult uploadAvatar(UploadFileDTO fileDTO) throws Exception {
        //判断文件大小
        if (!isFileSizeValid(fileDTO.getFile())){
            return new RestResult().error(ModuleErrorCode.Avatar_LARGE_ERROR);
        }
        // 创建目录（示例路径：E:/upload/）
        File dir = new File(expressCoreConfig.getImagePath());
        if (!dir.exists()) {dir.mkdirs();}

        // 生成新文件名（原始名+时间戳）
        String originalName = fileDTO.getFile().getOriginalFilename();
        String newName = UUID.randomUUID() + originalName.substring(originalName.lastIndexOf("."));

        // 保存文件
        File targetFile = new File(expressCoreConfig.getImagePath() + File.separator + newName);
        fileDTO.getFile().transferTo(targetFile);
        Map<String,String> map=new HashMap<>();
        String imageUrl=expressCoreConfig.getHost()+newName;
        map.put("imageUrl",imageUrl);
        return new RestResult().ok(map);
    }

    private boolean isFileSizeValid(MultipartFile file) {
        //// 1MB
        long MAX_SIZE = 1 * 1024 * 1024;
        if (file == null) {
            return false;
        }
        return file.getSize() <= MAX_SIZE;
    }


    private UserEntity insertWxUser(WxUserRegisterRequest request, SessionInfo sessionInfo) {
        UserEntity entity = new UserEntity();
        entity.setOpenId(sessionInfo.getOpenid());
        entity.setNickName(request.getUserInfo().getNickName());
        entity.setAvatarUrl(request.getUserInfo().getAvatarUrl());
        entity.setGender(request.getUserInfo().getGender());
        entity.setAddress(request.getUserInfo().getCountry()+","+request.getUserInfo().getProvince()+","+request.getUserInfo().getCity());
        insert(entity);
        return entity;
    }

    private SessionInfo getSessionByWxCode(String wxCode, String appid) throws Exception {
        String json = MiniProgramUtils.code2Session(appid, MyConstant.appSecret, wxCode, MyConstant.code2SessionUrl);
        log.info("微信小程序根据wxcode{}获取信息，返回：{}", wxCode, json);
        SessionInfo sessionInfo = JsonUtil.string2Obj(json, SessionInfo.class);
        if (sessionInfo == null || StringUtils.isEmpty(sessionInfo.getOpenid())) {
            return null;
        }
        return sessionInfo;
    }

}